import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';

import 'package:junyeyishu/utils/utils.dart';
import 'package:junyeyishu/widgets/QGWidget.dart';
import 'package:junyeyishu/widgets/QGEmpty.dart';

abstract class QGListState<T extends StatefulWidget> extends State<T> {
  String? tabURL;
  String tabKey = "data";
  dynamic tab;

  String? listURL;
  bool? isnopage = true;

  String listKey = "data";
  dynamic list;

  int? onshelfNum;



  SliverGridDelegate? gridDelegate;

  Map<dynamic, dynamic> tabParam() {
    return {};
  }

  Map<dynamic, dynamic> listParam() {
    return {};
  }

  onUpdateTab(data) {}
  onUpdateList(data) {}

  canUpdateList(data) {
    return true;
  }

  Widget itemBuilder(context, index, dynamic data) {
    return Container();
  }

  // #########
 
  int page = 1;
  var refreshController = EasyRefreshController(
      controlFinishRefresh: true, controlFinishLoad: true);

  Widget _buildItem(context, index) {
    if (list is List && list.length > index) {
      return itemBuilder(context, index, list[index]);
    }
    return Container();
  }
 
  buildList() {
    if (list == null) {
      return Expanded(
          child: Center(
              child: CircularProgressIndicator(color: Color(0xFFffffff))));
    }

    if (list is! List || list.isEmpty) {
      if (listURL == url_market_collectionList && onshelfNum == 0) {
        return Expanded(
          child: Stack(
            children: [
              QGEmpty(isExpanded: false),
              Container(
                alignment: Alignment.center,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    QGImage(asset: "delisted", width: 190.rpx),
                  ],
                ),
              ),
            ],
          ),
        );
      } else {
        return QGEmpty(isExpanded: true);
      }
    }
   
    return 
    Expanded(
      child: 
      isnopage == true?
      EasyRefresh(
          controller: refreshController,
          onLoad:onLoad,
          onRefresh: onRefresh,
          child: gridDelegate == null
              ?
              ListView.builder(
                  padding: EdgeInsets.zero,
                  itemCount: list is List ? list.length : 0,
                  itemBuilder: _buildItem)
              : GridView.builder(
                  gridDelegate: gridDelegate!,
                  padding: EdgeInsets.all(15.rpx),
                  itemCount: list is List ? list.length : 0,
                  itemBuilder:
                   _buildItem
                  )
      ):
      EasyRefresh(
          controller: refreshController,
          onRefresh: onRefresh,
          child: 
          gridDelegate == null
              ?
              ListView.builder(
                  padding: EdgeInsets.zero,
                  itemCount: list is List ? list.length : 0,
                  itemBuilder: _buildItem)
              : GridView.builder(
                  gridDelegate: gridDelegate!,
                  padding: EdgeInsets.all(15.rpx),
                  itemCount: list is List ? list.length : 0,
                  itemBuilder:
                   _buildItem
                  )
      )
    );
  }

  loadTab() {
    
    if (tabURL != null) {
      Network.post(tabURL, data: tabParam()).then((res) {
        if (!res.success) {
          toast(res.msg);
          return;
        }

        if (res.data is List) {
          tab = res.data;
        } else if (res.data is Map) {
          tab = res.data[tabKey];
        }



        onUpdateTab(tab);

        if (mounted) {
          setState(() {});
        }
      });
    }
  }

  onRefresh() {
    if (listURL == null) return;

    page = 1;

    var param = listParam();
    param["page"] = page;
    Map<String, dynamic> stringMap = param.cast<String, dynamic>();

     final data = FormData.fromMap(stringMap);
    

    Network.post(listURL, data: data).then((res) {
      if (!res.success) {
        toast(res.msg);
        list = [];
        setState(() {});
        return;
      }

      onResponse(res);

      if (res.data is String) {
        res.data = decryptToJson(res.data);
      }

      res.data = resetData(res.data);

      if (res.data is List) {
        if (!canUpdateList(res.data ?? [])) {
          refreshController.finishRefresh();
          refreshController.finishLoad();
          return;
        }
        list = res.data ?? [];
      } else if (res.data is Map) {
        if (!canUpdateList(res.data[listKey] ?? [])) {
          refreshController.finishRefresh();
          refreshController.finishLoad();
          return;
        }
        list = res.data[listKey] ?? [];
      }

      var allnums = 0;

      if (res.data is List) {
        allnums = int.parse("${res.ret?["allnums"] ?? "0"}");
        onshelfNum = res.ret?["onshelf_num"];
      } else if (res.data is Map) {
        allnums = int.parse("${res.data?["allnums"] ?? "0"}");
      }

      refreshController.finishRefresh();
      refreshController.finishLoad();

      if (list is List && list.length >= allnums) {
        refreshController.finishLoad(IndicatorResult.noMore);
      }
      onUpdateList(list);

      if (mounted) {
        setState(() {});
      }
    });
  }

  onLoad() {
    if (listURL == null) return;

    final param = listParam();
    param["page"] = ++page;
     
        Map<String, dynamic> stringMap = param.cast<String, dynamic>();

    Network.post(listURL, data: stringMap).then((res) {
      if (!res.success) {
        toast(res.msg);
        page -= 1;
        refreshController.finishLoad(IndicatorResult.fail);
        return;
      }

      if (res.data is String) {
        res.data = decryptToJson(res.data);
      }

      res.data = resetData(res.data);

      var temp = [];

      if (res.data is List) {
        temp = res.data ?? [];
      } else if (res.data is Map) {
        temp = res.data[listKey] ?? [];
      }
      var allnums = 0;

      if (res.data is List) {
        allnums = int.parse("${res.ret?["allnums"] ?? "0"}");
      } else if (res.data is Map) {
        allnums = int.parse("${res.data?["allnums"] ?? "0"}");
      }

      list.addAll(temp);

      if (list.length >= allnums) {
        refreshController.finishLoad(IndicatorResult.noMore);
      } else {
        refreshController.finishLoad();
      }

      onUpdateList(list);
      if (mounted) setState(() {});
    });
  }

  resetData(data) {
    return data;
  }

  onResponse(res) {}
}
